SQlite源码分析

Wal文件格式

        WAL日志包括一个头和0到多个框(frames),每个框记录一个页(page)修改的内容。对数据库所有的修改都通过修改框的方式写入WAL日志。单个的WAL日志可记录多个事务。WAL日志中的内容会定期修改到数据库文件中,这个操作成为检查点。
        单个WAL日志可多次使用。也就是说,WAL可以被框占满,当检查点动作过后,其他的框又能写到原来的位置上。WAL日志总是从开始到结尾顺序增长。附加到框后面的检查总数(checksums)和计数(counters)用来确定WAL中的那些框有效,哪些框是以前检查点动作操作完成的。
        WAL头有32字节长,包括以下8个32位的大端无符号整数

  • 0: Magic number. 0x377f0682 or 0x377f0683

  • 4: File format version. Currently 3007000

  • 8: Database page size. Example: 1024

  • 12: Checkpoint sequence number

  • 16: Salt-1, random integer incremented with each checkpoint

  • 20: Salt-2, a different random integer changing with each ckpt

  • 24: Checksum-1 (first part of checksum for first 24 bytes of header).

  • 28: Checksum-2 (second part of checksum for first 24 bytes of header).

        在Wal.c中实现:
   struct WalIndexHdr {
   u32 iVersion;
   wal索引版本
   u32 unused; 未使用区域
    u32 iChange; 每次事务的计数器
   u8 isInit;
   u8 bigEndCksum; 判断wal中的checksum的类型是否为big-endian
   u16 szPage; 数据库page数量
   u32 mxFrame; WAL中最后一个有效帧的索引
   u32 nPage; 数据库中的页大小
   u32 aFrameCksum[2]; 日志最后一帧的checksum
   u32 aSalt[2]; 从WAL头复制两个salt值
   u32 aCksum[2];
       预写日志文件是由下列对象的一个实例来表示。    struct Wal {
    sqlite3_vfs pVfs; //用来创建pDbFd的VFS
    sqlite3_file
pDbFd; //数据库文件
    sqlite3_file pWalFd; //WAL文件
    u32 iCallback; //传递给回调日志的值
    i64 mxWalSize; //复位后调整WAL到这个大小
    int nWiData; //apWiData数组的大小
    int szFirstBlock; //写入WAL文件的第一个块的大小
    uolatile u32 ** apWiData ; //指向内存中WAL索引内容
    u32 szPage ; //数据库页面大小
    i16 readLock ; //读哪个锁正在举行。 -1表示无
    u8 syncFlags ; //标志使用同步头写
    u8 exclusiveMode ; //非零,如果连接是独占模式
    u8 writeLock ; //如果真在写事务
    u8 ckptLock ; //如果真拿着一个检查站锁定
    u8 readonly; //WAL_RDWR , WAL_RDONLY ,或WAL_SHM_RDONLY
    u8 truncateOnCommit ; //真正截断WAL上提交的文件
    u8 syncHeader ; //FSYNC沃尔玛头如果为true
    u8 padToSectorBoundary //垫记录到下一个扇区
    walIndexHdr HDR ; //为当前事务wal索引头
    const char
zWalName ; //WAL文件的文件名
    u32 nCkpt ; //wal检查点序列计数器\
# IFDEF SQLITE_DEBUG
    u8 LOCKERROR ; //发生锁定错误时
   # ENDIF
   } ;